<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    // 解构赋值：同时使用数组或对象属性中保存的多个值分别为多个变量赋值
    // 1，数组
    // es2015之前通过下标取值，es2015可将数组多个值保存在多个变量中
    var fruits = ["苹果", "橘子", "梨"];
    var [apple, orange, pear] = fruits;
    console.log(apple, orange, pear); // 苹果 橘子 梨
    // 只取一部分
    var [,orange1] = fruits;
    console.log(orange1); // 橘子
    // 当变量不在数组中，使用默认值构值
    var fruits = ["苹果", "橘子"];
    var [apple="apple", orange="orange", pear="pear"] = fruits;
    console.log(apple, orange, pear); //苹果 橘子 pear

    // 2，使用spread运算符（代码中的...)
    /*es2015之前使用apply方法结合Math.max方法获取数组最大值
    es2015中使用spread运算符将数组传递作为函数的参数值*/
    var max1 = Math.max.apply(null, [-1, 200, 30, -99, 0]);
    var max2 = Math.max(...[-1, 200, 30, -99, 0]);
    console.log(max1, max2); // 200 200
    // 使用spread运算符将数组中未赋值元素归结到一个变量中
    var fruits = ["苹果", "橘子", "梨"];
    var [apple, ...others] = fruits;
    console.log(apple, others);
    // 利用spread运算符将一个数组插入到数组中变成一系列数组元素，而不是嵌套数组
    var cities = ["北京", "武汉"];
    var places = ["江苏", ...cities, "山东"];
    console.log(places);
    // es2017中可对 对象 使用spread运算符
    var {a, b, ...c} = {a: 1, b: 2, c: 3, d: 4, e: 5};
    console.log(a, b, c);   // 1 2 {c: 3, d: 4, e: 5}
    // 重新组合成一个对象
    var newObj = {a, b, ...c}; // {a: 1, b: 2, c: 3, d: 4, e: 5}
    console.log(newObj);

    // 3，同时使用对象的多个属性分别给多个变量赋值
    var fruits = {apple: "苹果", orange: "橘子", pear: "梨"};
    // 变量名和对象的属性名必须相同，否则值为undefined
    // 这里可看出： 就相当于直接从对象中取出属性来使用一样
    var {apple, orange, pear} = fruits;
    console.log(apple, orange, pear); // 苹果 橘子 梨
    var {apple1, orange1, pear1} = fruits; // undefined undefined undefined
    console.log(apple1, orange1, pear1);
    // 变量的顺序可与属性顺序不一致（对象没有顺序的概念）
    var digital = {a: 1, b: 2, c: 3};
    var {c, a, b} = digital;
    console.log(a, b, c); // 1 2 3
    // 只取一部分
    var {pear} = fruits;
    console.log(pear); // 梨
    // 变量不在对象属性名中，使用默认值赋值，若又没有默认值，则为undefined
    var xy = {x: 1, y: 2};
    var {x, y, z=3, last} = xy;
    console.log(x, y, z, last); // 1 2 3 undefined
    // 可对属性值赋给其他变量（重新赋值）
    var {apple: newApple, orange: newOrange, pear: newPear} = fruits;
    console.log(newApple, newOrange, newPear); // 苹果 橘子 梨

    //4， 多个阶层中使用解构赋值
    // 4，1，多维数组
    var user = [
        ["张", "雪莹"],
        ["夏", "雨荷"],
        ["箫", "婧雅"]
    ];
    var [, [firstName, lastName]] = user;
    console.log(firstName, lastName); // 夏 雨荷
    // 4,2,数组嵌套对象
    var user1 = [
        {firstName: "张", lastName: "雪莹"},
        {firstName: "夏", lastName: "雨荷"},
        {firstName: "箫", lastName: "婧雅"}
    ];
    var [, , {firstName, lastName}] = user1;
    console.log(firstName, lastName); // 箫 婧雅
    var [{firstName: newFirstName, lastName: newLastName}] = user1;
    console.log(newFirstName, newLastName); // 张 雪莹
    // 4,3, 对象嵌套对象
    var user2 = {
        subUser1: {firstName: "张", lastName: "雪莹", pinyin: "zhang xue ying"},
        subUser2: {firstName: "夏", lastName: "雨荷", pinyin: "xia yu he"},
        subUser3: {firstName: "箫", lastName: "婧雅", pinyin: "xiao jing ya"}
    };
    // 因为对象是无序的，所以不像数组那样取某个值时需要使用,,,等，可直接取值
    var { subUser3: {firstName: newFirstName, lastName: newLastName, pinyin: newPinYin}} = user2;
    console.log(newFirstName, newLastName, newPinYin); // 箫 婧雅 xiao jing ya

    // 5，解构赋值的示例
    // 5，1，使用解构赋值简化代码
    // es2015之前；
    var list = [1, 2, 3];
    var length = list.length;
    var first = list[0];
    console.log(length, first); // 3 1
    // es2015
    var {length} = list;        // 获取数组的长度
    let [, , last1] = list;
    console.log(length, last1); // 3 3
    // 5，2 在forEach或for-of循环中使用
    var users = [
        ["张", "雪莹"],
        ["夏", "雨荷"],
        ["箫", "婧雅"]
    ];
    // forEach(function(value, index, arr)): 第一个值value表示数组中的元素，遍历每个元素
    users.forEach(([firstName, lastName]) => {  // 在参数中使用解构赋值
        console.log(`姓名：${firstName}${lastName}`);
    }); // 姓名：张雪莹 姓名：夏雨荷 姓名：箫婧雅
    for (var [firstName, lastName] of users) {
        console.log(`姓名：${firstName}${lastName}`);
    } // 姓名：张雪莹 姓名：夏雨荷 姓名：箫婧雅
    // 5，3， 变量值进行交换
    var a = 1, b = 2, c = 3;
    [a, b, c] = [c, a, b];
    console.log(a, b, c); // 3 1 2
    // 6，可多次使用不同的数组给同一些变量使用解构赋值
    var [a, b, c] = ["a", "b", "c"];
    console.log(a, b, c);  // a b c
    [a, b, c] = ["A", "B", "C"];
    console.log(a, b, c);  // A B C
    // 6，2，第一次使用对象给一些变量使用解构赋值之后，不能再使用对象给这些变量解构赋值
    // 只能将语句用括号括起来才不会出错
    var {a, b, c} = {a: "a", b: "b", c: "c"};
    console.log(a, b, c);
    // {a, b, c} = {a: "A", b: "B", c:"C"};
    console.log(a, b, c);   // SyntaxError: Unexpected token =
    ({a, b, c} = {a: "A", b: "B", c: "C"});
    console.log(a, b, c);   // A B C
    // 但是再次声明这些变量则不会出错（相当于重新声明一个变量）
    var {a, b, c} = {a: "A", b: "B", c: "C"};
    console.log(a, b, c);   //  A B C
</script>
</body>
</html>